package test.module;

import static arch.chameleon.support.constants.WebConstants.REQ_HEADER_X_REQUESTED_WITH;
import static arch.chameleon.support.constants.WebConstants.REQ_MESSAGE;
import static arch.chameleon.support.constants.WebConstants.*;
import static org.junit.Assert.*;

import java.util.HashMap;
import java.util.Map;

import org.junit.After;
import org.junit.Before;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import arch.chameleon.support.util.JsonUtils;

import com.meterware.httpunit.GetMethodWebRequest;
import com.meterware.httpunit.PostMethodWebRequest;
import com.meterware.httpunit.WebConversation;
import com.meterware.httpunit.WebRequest;
import com.meterware.httpunit.WebResponse;


/**
 * AJAX整合测试基类
 * @author George
 *
 */
public abstract class AbstractAjaxIntegratedTestSupport{

	protected transient Logger log = LoggerFactory.getLogger(this.getClass());
	
	protected WebConversation converstaion;
	
	protected static final String URL_PREFIX = "http://127.0.0.1:8080/chameleon/";
	
	@Before
	public void setUp(){
		converstaion = new WebConversation();
	}
	
	/**
	 * 登录
	 */
	protected void login(){
		authenticate(buildURL("authentication.json"), "authenticate", "admin", "admin123");	
	}
	
	/**
	 * URL构成：前缀(http://ip:port/webcontext/) + 请求(xxx.json)
	 * @param prefix
	 * @param req
	 * @return
	 */
	protected String buildURL(String prefix, String req){
		return prefix + req;
	}
	
	/**
	 * URL构成：请求(xxx.json)
	 * @param req
	 * @return
	 */
	protected String buildURL(String req){
		return URL_PREFIX + req;
	}
	
	/**
	 * 登录身份验证(如有验证码，须屏蔽，请配置configurations-dev.properties#captcha.ignore=true)
	 * @param url
	 * @param operate
	 * @param username 用户名
	 * @param password 密码
	 * @return
	 */
	protected Map<String, Object>  authenticate(String url, String operate, String username, String password){
		Map<String, Object> params = new HashMap<String, Object>();
		params.put(USERNAME_PARAM_NAME, username);
		params.put(PASSWORD_PARAM_NAME, password);
		params.put(CAPTCHA_PARAM_NAME, "");
		return doPostRequest(url, operate, params);
	}
	
	/**
	 * 发送POST请求
	 * @param url
	 * @param operate
	 * @param params
	 * @return
	 */
	protected Map<String, Object>  doPostRequest(String url, String operate, Map<String, Object> params){
		return doRequest(url, MethodType.POST, operate, params);		
	}
	
	/**
	 * 发送GET请求
	 * @param url
	 * @param operate
	 * @param params
	 * @return
	 */
	protected Map<String, Object>  doGetRequest(String url, String operate, Map<String, Object> params){
		return doRequest(url, MethodType.GET, operate, params);
	}
	
	/**
	 * 发送POST/GET请求
	 * @param url
	 * @param methodType
	 * @param operate
	 * @param params
	 * @return
	 */
	private Map<String, Object> doRequest(String url, MethodType methodType, String operate, Map<String, Object> params){
		Map<String, Object> respJsonObj = null;
		try{
			WebRequest request = methodType == MethodType.POST ? 
					new PostMethodWebRequest(url) : new GetMethodWebRequest(url);
			//设置XHR头
			request.setHeaderField(REQ_HEADER_X_REQUESTED_WITH, REQ_TYPE_XHR);
			
			//组装请求参数
			Map<String, Object> requestParameters = new HashMap<String, Object>();
			//头参数
			Map<String, Object> parameterHead = new HashMap<String, Object>();
			parameterHead.put(OPERATE, operate);
			
			requestParameters.put(REQ_HEAD, parameterHead);			
			requestParameters.put(REQ_BODY, params);
			
			//转换requestParameters为json
			String jsonParams = JsonUtils.object2JsonString(requestParameters);
			
			log.info("REQUEST: {}", new Object[]{jsonParams});
			
			//设置请求参数
			request.setParameter(REQ_MESSAGE, jsonParams);
			
			WebResponse response = converstaion.getResponse(request);
			
			String respText = response.getText();
			
			log.info("RESPONSE: {}", new Object[]{respText});
			
			respJsonObj = JsonUtils.jsonString2Map(respText);
			
			String respStatus = String.valueOf(((Map)respJsonObj.get(RSP_HEAD)).get(RSP_STATUS));
			
			if(respStatus.equals(RSP_STATUS_SUCCESS)){
				//do nothing
			}else if(respStatus.equals(RSP_STATUS_FAILURE)){
				throw new Throwable(String.format("response failed: %s", String.valueOf(((Map)respJsonObj.get(RSP_HEAD)).get(RSP_MSG))));
			}else if(respStatus.equals(RSP_STATUS_SESSION_EXPIRE)){
				throw new Throwable("session expired");
			}else{
				throw new Throwable("unknown response status");
			}
		}catch(Throwable t){
			log.error(t.getMessage(), t);
			fail();
		}
		return (Map)respJsonObj.get(RSP_BODY);
	}
	
	@After
	public void tearDown(){
		converstaion = null;
	}
	
	public static enum MethodType{
		GET,
		POST
	}
}
